package points

import (
	"context"
	"encoding/json"
	"fmt"
	"net/url"
	"sale-admin/config"
	"sale-admin/config/mysql"
	"sale-admin/config/redis"
	"sale-admin/internal/define"
	"sale-admin/internal/models"
	"strconv"
	"strings"
	"time"

	"192.168.1.75/go-pkg/errorx"
	"192.168.1.75/go-pkg/helper"
	"192.168.1.75/go-pkg/logx"
	"gorm.io/gorm"
)

type ZhengHongPoints struct {
	PointsInterface
}

const (
	ZHENGHONG_SUCCESS = "PUB-00000"
)

// body:  `{"flowNo":"011810240004","creditType":"1","tranMode":"0","billGoodsList":[{"goodsCode":"201000002","goodsName":"上衣","goodsCount":"1","price":"8"}],"billPayList":[{"paymentTypeCode":"01","paymentTypeName":"现金","paymentNo":"1","paymentAmount":"8","changeAmount":"0"}],"realAmt":"8","srcAmt":"8","favAmt":"2","invoiceAmt":"8","cardId":"880600008086","shopId":"2011809020001","userAccount":"000","posNo":"01","filDate":"2018-10-24 10:25:25","exceptionRefund":"1","rebatePoint":"8","totalPoint":"24290","isRefunded":""}`

// GetSign 获取签名
// queryMap query字段
// params body字段
func (ZhengHongPoints) GetQueryString(ctx context.Context, SalesID string, queryMap map[string]string, params *string) (queryString string, err error) {
	accessToken, err1 := ZhengHongPoints{}.GetAccessToken(ctx, SalesID)
	if err1 != nil {
		logx.Error(ctx, "zhenghong get access token", logx.Any("error", err1))
		return "", err1
	}
	rnd, _ := helper.UUID{}.String()
	timestamp := time.Now().Unix()

	var URL url.URL
	query := URL.Query()
	query.Add("accessToken", accessToken)
	query.Add("rnd", rnd)
	query.Add("appKey", config.Config.ZhenghongPoints.APPKey)
	if params != nil {
		query.Add("body", *params)
	}
	query.Add("timestamp", strconv.Itoa(int(timestamp)))
	if len(queryMap) > 0 {
		for key, val := range queryMap {
			query.Add(key, val)
		}
	}
	queryString = query.Encode()

	md5String := helper.Md5(queryString + config.Config.ZhenghongPoints.APPSecret)
	if params != nil {
		query.Del("body") //body参与签名但不拼接queryString
	}
	queryString = query.Encode() + "&sign=" + strings.ToUpper(md5String) + "&signType=md5"
	return queryString, nil
}

type ZhenghongDeviceLoginRsp struct {
	ErrorCode    string      `json:"errorCode"`
	ErrorMessage string      `json:"errorMessage"`
	ErrorCodeMsg interface{} `json:"errorCodeMsg"`
	Extra        interface{} `json:"extra"`
	Display      bool        `json:"display"`
	Exception    interface{} `json:"exception"`
	ReqTime      int         `json:"reqTime"`
	CostTime     int         `json:"costTime"`
	SkipType     interface{} `json:"skipType"`
	ServiceTime  int         `json:"serviceTime"`
	SkipParam    interface{} `json:"skipParam"`
	Body         Body        `json:"body"`
	Encrypted    bool        `json:"encrypted"`
}
type Body struct {
	WorkKey                string `json:"workKey"`
	AccessToken            string `json:"accessToken"`
	RegisterTime           int    `json:"registerTime"`
	SessionValiditySeconds int    `json:"sessionValiditySeconds"`
}

func NewZhenghongPoints() PointsInterface {
	return &ZhengHongPoints{}
}

// 设备登陆
// 获取accessToken
func (ZhengHongPoints) GetAccessToken(ctx context.Context, SalesID string) (accessToken string, err error) {
	rdb := redis.NewDB()
	AccessToken, err1 := rdb.HGet(ctx, define.RedisZhengHongPointsAccessToken, SalesID).Result()
	if AccessToken != "" && err1 == nil {
		return AccessToken, nil
	}

	// 重新登录
	rnd, _ := helper.UUID{}.String()

	var URL url.URL
	query := URL.Query()
	query.Add("deviceId", SalesID)
	query.Add("appKey", config.Config.ZhenghongPoints.APPKey)
	query.Add("rnd", rnd)
	PostURL := config.Config.ZhenghongPoints.BaseURL + "/api/v3/securities/devices/register?" + query.Encode()

	statusCode, bytes, err := helper.Net{}.Request(ctx, "POST", PostURL, map[string]string{}, nil)
	var res ZhenghongDeviceLoginRsp
	json.Unmarshal(bytes, &res)
	logx.Error(ctx, "zhenghong devices register", logx.Any("url", PostURL), logx.Any("res", res), logx.Any("statusCode", statusCode), logx.Any("err", err))
	if statusCode != 200 || err != nil {
		return "", errorx.New("设备登录错误", -1)
	}
	if res.ErrorCode != ZHENGHONG_SUCCESS {
		return "", errorx.New(res.ErrorMessage, -1)
	}
	//写入缓存
	rdb.HSet(ctx, define.RedisZhengHongPointsAccessToken, SalesID, res.Body.AccessToken)
	rdb.Expire(ctx, define.RedisZhengHongPointsAccessToken, time.Duration(res.Body.SessionValiditySeconds/2)*time.Second)
	return res.Body.AccessToken, nil
}

type ZhenghongCommonReq struct {
	ErrorCode    string      `json:"errorCode"`
	ErrorMessage string      `json:"errorMessage"`
	ErrorCodeMsg string      `json:"errorCodeMsg"`
	Extra        interface{} `json:"extra"`
	Display      bool        `json:"display"`
	Exception    interface{} `json:"exception"`
	ReqTime      int         `json:"reqTime"`
	CostTime     int         `json:"costTime"`
	SkipType     interface{} `json:"skipType"`
	ServiceTime  int         `json:"serviceTime"`
	SkipParam    interface{} `json:"skipParam"`
	Encrypted    bool        `json:"encrypted"`
}
type ZhenghongGetMemberInfoRsp struct {
	ZhenghongCommonReq
	Body ZhenghongMemberInfoBody `json:"body"`
}

type ZhenghongMemberInfoLevel struct {
	ID                           string      `json:"id"`
	Code                         string      `json:"code"`
	Name                         string      `json:"name"`
	Icon                         string      `json:"icon"`
	LevelType                    string      `json:"levelType"`
	LevelLabel                   interface{} `json:"levelLabel"`
	MostBindCarPlateCount        int         `json:"mostBindCarPlateCount"`
	LeftBindCarPlateCount        interface{} `json:"leftBindCarPlateCount"`
	CanBindCarPlate              bool        `json:"canBindCarPlate"`
	SkinID                       interface{} `json:"skinId"`
	SkinImgURL                   interface{} `json:"skinImgUrl"`
	SkinName                     interface{} `json:"skinName"`
	Level                        int         `json:"level"`
	BindCarPlateTimeCycle        string      `json:"bindCarPlateTimeCycle"`
	BindCarPlateTimesInCycle     int         `json:"bindCarPlateTimesInCycle"`
	LeftBindCarPlateTimesInCycle interface{} `json:"leftBindCarPlateTimesInCycle"`
}
type ZhenghongMemberInfoBody struct {
	ID                              string                   `json:"id"`                  //会员ID
	CardID                          interface{}              `json:"cardId"`              //会员卡id
	Name                            interface{}              `json:"name"`                //会员姓名
	Gender                          int                      `json:"gender"`              //性别 0未知 1男 2女
	Phone                           string                   `json:"phone"`               //手机号码
	Birthday                        string                   `json:"birthday"`            //生日
	NickName                        string                   `json:"nickName"`            //会员昵称
	HeadImg                         string                   `json:"headImg"`             //头像
	Level                           ZhenghongMemberInfoLevel `json:"level"`               //会员级别
	CouponCount                     int                      `json:"couponCount"`         //拥有的优惠券数量
	CaredCount                      int                      `json:"caredCount"`          //关注的商户数量
	NormalCouponCount               int                      `json:"normalCouponCount"`   //未使用的优惠券数量
	Credit                          string                   `json:"credit"`              //【【【【【【【【【【积分账户余额】】】】】】】】】】
	EwalletBalance                  string                   `json:"ewalletBalance"`      //储值账户余额
	BindCrmVipcard                  bool                     `json:"bindCrmVipcard"`      //是否绑定会员卡
	CardNo                          string                   `json:"cardNo"`              //会员卡号
	CrmVipcardStatus                int                      `json:"crmVipcardStatus"`    //会员卡状态 15未开通 20正常 30已禁用 40已挂失 60已注销 70冻结
	CarPlate                        string                   `json:"carPlate"`            //车牌号
	MallInfo                        interface{}              `json:"mallInfo"`            //门店信息
	MallID                          string                   `json:"mallId"`              //门店id
	Job                             string                   `json:"job"`                 //职业
	ParkingTicketCount              int                      `json:"parkingTicketCount"`  //停车券数量
	NewsCount                       int                      `json:"newsCount"`           //未读信息数量
	HasSigned                       bool                     `json:"hasSigned"`           //是否签到
	NeedMoreInfo                    bool                     `json:"needMoreInfo"`        //注册所需的信息是否填写
	OpenIds                         interface{}              `json:"openIds"`             //openid列表
	OpenIDSources                   interface{}              `json:"openIdSources"`       //openid来源列表  source：portal_weixin 微信公众号，portal_web 网页用户端	mini_weixin 微信小程序	app_ios 苹果用户端app_android 安卓用户端
	InfoIsCompleted                 bool                     `json:"infoIsCompleted"`     //是否完善资料所需的信息字段
	DeliveryAddressList             []interface{}            `json:"deliveryAddressList"` //会员邮寄收货地址列表
	CrmVipcardStatusText            interface{}              `json:"crmVipcardStatusText"`
	Hobbies                         []interface{}            `json:"hobbies"`
	OpenID                          interface{}              `json:"openId"`
	CarPlateList                    []interface{}            `json:"carPlateList"`
	Address                         interface{}              `json:"address"`
	IDCard                          interface{}              `json:"idCard"`
	ParkingPaymentPattern           interface{}              `json:"parkingPaymentPattern"`
	UnionID                         interface{}              `json:"unionId"`
	QrCode                          interface{}              `json:"qrCode"`
	MemberAutoParkingPayMandateList []interface{}            `json:"memberAutoParkingPayMandateList"`
	ExtendInfos                     []interface{}            `json:"extendInfos"`
	Email                           interface{}              `json:"email"`
	CreditExpireDate                interface{}              `json:"creditExpireDate"`
	LevelStartTime                  interface{}              `json:"levelStartTime"`
	LevelEndTime                    interface{}              `json:"levelEndTime"`
	AlipayUserID                    interface{}              `json:"alipayUserId"`
	AlipayUserIDList                interface{}              `json:"alipayUserIdList"`
	LogoutTag                       interface{}              `json:"logoutTag"`
	CardValidDate                   interface{}              `json:"cardValidDate"`
	MemberChildrenInfo              interface{}              `json:"memberChildrenInfo"`
	CanModifyBirthday               interface{}              `json:"canModifyBirthday"`
	LatelyCheckTime                 interface{}              `json:"latelyCheckTime"`
	SubscribeNoteRemind             interface{}              `json:"subscribeNoteRemind"`
	PopMessageList                  interface{}              `json:"popMessageList"`
	BehaviorInfo                    interface{}              `json:"behaviorInfo"`
	UnlicensedCar                   interface{}              `json:"unlicensedCar"`
	HasEshopOrder                   interface{}              `json:"hasEshopOrder"`
	MemberDiscountInfo              interface{}              `json:"memberDiscountInfo"`
	GrowUp                          interface{}              `json:"growUp"`
	ByteDanceOpenID                 interface{}              `json:"byteDanceOpenId"`
	ByteDanceOpenIds                interface{}              `json:"byteDanceOpenIds"`
	ByteDanceUnionID                interface{}              `json:"byteDanceUnionId"`
	AutonymStatus                   int                      `json:"autonymStatus"`
	MarriageStatus                  string                   `json:"marriageStatus"`
	IsOpenCard                      bool                     `json:"isOpenCard"`
	LevelIsNew                      bool                     `json:"levelIsNew"`
	UpgradeProgress                 string                   `json:"upgradeProgress"`
	HavePayPassword                 bool                     `json:"havePayPassword"`
	CmbcJointMember                 bool                     `json:"cmbcJointMember"`
	MinPayNoPassword                int                      `json:"minPayNoPassword"`
	UseMemberBenefits               bool                     `json:"useMemberBenefits"`
	WillExpireCredit                string                   `json:"willExpireCredit"`
	HisCredit                       string                   `json:"hisCredit"`
	CurrentTime                     int                      `json:"currentTime"`
	ParkingPaymentStatus            int                      `json:"parkingPaymentStatus"`
	ExternalCouponCount             int                      `json:"externalCouponCount"`
	CreditCardCount                 int                      `json:"creditCardCount"`
	CanUseCreditCardCount           int                      `json:"canUseCreditCardCount"`
	CountingCardCount               string                   `json:"countingCardCount"`
	CanUseCountingCardCount         int                      `json:"canUseCountingCardCount"`
	GrowUpBalance                   string                   `json:"growUpBalance"`
	ActivateTime                    int                      `json:"activateTime"`
	RegTime                         string                   `json:"regTime"`
	CardTypeName                    string                   `json:"cardTypeName"`
	CurrentAddedCredit              string                   `json:"currentAddedCredit"`
	CreditAccountTotalRecharge      string                   `json:"creditAccountTotalRecharge"`
	JoinedCard                      bool                     `json:"joinedCard"`
	FirstOrder                      bool                     `json:"firstOrder"`
	Logout                          bool                     `json:"logout"`
	PopMessage                      bool                     `json:"popMessage"`
}

// 4.2 查询会员资料[当前使用phone方式]
func (ZhengHongPoints) GetMemberInfo(ctx context.Context, db *gorm.DB, SalesID, phone, openid string) (data MemberMsg, err error) {
	queryMap := make(map[string]string)
	queryMap["type"] = "phone"
	queryMap["value"] = phone
	queryString, err1 := ZhengHongPoints{}.GetQueryString(ctx, SalesID, queryMap, nil)
	if err1 != nil {
		return data, err1
	}

	QueryURL := config.Config.ZhenghongPoints.BaseURL + "/api/v3/member/info?" + queryString
	statusCode, bytes, err := helper.Net{}.Request(ctx, "GET", QueryURL, map[string]string{}, nil)
	var res ZhenghongGetMemberInfoRsp
	json.Unmarshal(bytes, &res)
	logx.Info(ctx, "get member info", logx.Any("queryURL", QueryURL), logx.Any("statusCode", statusCode), logx.Any("bytes", string(bytes)), logx.Any("err", err))

	if res.ErrorCode != ZHENGHONG_SUCCESS {
		err = errorx.New(res.ErrorMessage)
		return
	}
	var rsp MemberMsg
	rsp.NickName = res.Body.NickName
	rsp.Points, _ = strconv.ParseFloat(res.Body.Credit, 64)
	rsp.HeadImg = res.Body.HeadImg
	rsp.Phone = res.Body.Phone
	rsp.ID = res.Body.ID
	rsp.CardNo = res.Body.CardNo

	return rsp, nil
}

type ZhenghongMemberRegistRsp struct {
	ZhenghongCommonReq
	Body ZhenghongMemberRegistBody `json:"body"`
}
type ZhenghongMemberRegistBody struct {
	ID              string            `json:"id"`
	Name            interface{}       `json:"name"`
	NickName        string            `json:"nickName"`
	NickNameEncoded interface{}       `json:"nickNameEncoded"`
	NewCard         interface{}       `json:"newCard"`
	Sid             interface{}       `json:"sid"`
	NeedBindPhone   bool              `json:"needBindPhone"`
	Mobile          string            `json:"mobile"`
	MallInfo        ZhenghongMallInfo `json:"mallInfo"`
	NeedMoreInfo    bool              `json:"needMoreInfo"`
	Channel         interface{}       `json:"channel"`
	MemberLevelID   string            `json:"memberLevelId"`
	AgreeProtocol   interface{}       `json:"agreeProtocol"`
	SzcNextStep     interface{}       `json:"szcNextStep"`
	MemberInfoResp  interface{}       `json:"memberInfoResp"`
	UnlicensedCar   interface{}       `json:"unlicensedCar"`
	NextStep        bool              `json:"nextStep"`
	NewMobcbCard    bool              `json:"newMobcbCard"`
	NewCreateCard   bool              `json:"newCreateCard"`
}
type ZhenghongMallInfo struct {
	ID          string      `json:"id"`
	Code        string      `json:"code"`
	Name        string      `json:"name"`
	Icon        interface{} `json:"icon"`
	NameInitial interface{} `json:"nameInitial"`
	TypeID      interface{} `json:"typeId"`
	TypeName    interface{} `json:"typeName"`
}

// 4.1 MemberRegist 会员注册
// mallID, phone 必填
func (ZhengHongPoints) MemberRegist(ctx context.Context, db *gorm.DB, SalesID, mallID,
	phone, name string, gender int, birthday, idCard, Openid,
	headImg, provinceId, cityId, areaId, address string) (err error) {
	if mallID == "" {
		return errorx.New("门店ID不能为空", -1)
	}

	// 正弘注册用户信息
	var PostData = make(map[string]interface{})
	PostData["mallID"] = mallID
	PostData["phone"] = phone
	if name != "" {
		PostData["name"] = name
	}
	PostData["gender"] = gender
	if birthday != "" {
		PostData["birthday"] = birthday
	}
	if idCard != "" {
		PostData["idCard"] = idCard
	}
	if Openid != "" {
		PostData["portalWxOpenid"] = Openid
	}
	if headImg != "" {
		PostData["headImg"] = headImg
	}
	if provinceId != "" {
		PostData["provinceId"] = provinceId
	}
	if cityId != "" {
		PostData["cityId"] = cityId
	}
	if areaId != "" {
		PostData["areaId"] = areaId
	}
	if address != "" {
		PostData["address"] = address
	}
	bytes, _ := json.Marshal(&PostData)
	var params = string(bytes)
	queryString, err1 := ZhengHongPoints{}.GetQueryString(ctx, SalesID, map[string]string{}, &params)
	if err1 != nil {
		return err1
	}

	QueryURL := config.Config.ZhenghongPoints.BaseURL + "/api/v3/member/regist?" + queryString
	statusCode, bytes, err := helper.Net{}.Request(ctx, "POST", QueryURL, map[string]string{}, PostData)
	var res ZhenghongMemberRegistRsp
	json.Unmarshal(bytes, &res)
	logx.Info(ctx, "member regist", logx.Any("queryURL", QueryURL), logx.Any("statusCode", statusCode), logx.Any("bytes", string(bytes)), logx.Any("err", err))

	if res.ErrorCode != ZHENGHONG_SUCCESS {
		err = errorx.New(res.ErrorMessage)
		return
	}
	return
}

type ZhenghongBalanceQueryRsp struct {
	ZhenghongCommonReq
	Body ZhenghongBalanceQueryBody `json:"body"`
}
type ZhenghongBalanceQueryBody struct {
	MemberID      string      `json:"memberId"`      //会员ID
	CardNo        string      `json:"cardNo"`        //会员卡号
	Point         string      `json:"point"`         //会员积分
	PointString   string      `json:"pointString"`   //会员积分
	Balance       int         `json:"balance"`       //会员储值余额，单位分
	BalanceString interface{} `json:"balanceString"` //会员储值余额
	CardType      string      `json:"cardType"`      // member -- 会员卡
}

// 4.3 PointsQuery 积分余额查询
func (ZhengHongPoints) PointsQuery(ctx context.Context, SalesID, openid, mallId string) (points float64, err error) {
	db := mysql.NewDB()
	var WechatUserInfo models.MaWechatUser
	var WechatUserCount int64
	db.Model(&models.MaWechatUser{}).
		Where("open_id = ?", openid).
		Take(&WechatUserInfo).
		Count(&WechatUserCount)
	if WechatUserCount == 0 || WechatUserInfo.Phone == "" {
		err = errorx.New("【正弘城】当前用户未注册", 100099)
		return
	}
	// 验证正弘系统会否注册用户
	memberRsp, err := ZhengHongPoints{}.GetMemberInfo(ctx, db, SalesID, WechatUserInfo.Phone, WechatUserInfo.OpenID)
	if memberRsp.ID == "" || err != nil {
		err = errorx.New("【正弘城】当前用户未注册", 100099)
		return
	}

	//请求积分余额
	queryString, err1 := ZhengHongPoints{}.GetQueryString(ctx, SalesID, nil, nil)
	if err1 != nil {
		err = err1
		return
	}

	URI := config.Config.ZhenghongPoints.BaseURL + fmt.Sprintf("/api/v3/card/accountBalance/query/%s?", memberRsp.ID)
	QueryURL := URI + queryString
	statusCode, bytes, err := helper.Net{}.Request(ctx, "GET", QueryURL, nil, nil)
	var rsp ZhenghongBalanceQueryRsp
	json.Unmarshal(bytes, &rsp)
	logx.Info(ctx, "balance query", logx.Any("queryURL", QueryURL), logx.Any("statusCode", statusCode), logx.Any("bytes", string(bytes)), logx.Any("err", err))

	if rsp.ErrorCode != ZHENGHONG_SUCCESS {
		err = errorx.New(rsp.ErrorMessage)
		return
	}
	TotalPoints, _ := strconv.ParseFloat(rsp.Body.Point, 64)
	return TotalPoints, nil
}

// 4.4 BalanceTrade 积分余额支付
// SalesID             //必填 机器码
// cardNo              //必填 会员卡号
// tradeType           //必填 交易类型 recharge 增加 consume 扣减 revoke 冲正
// tradeAmount         //必填 交易数额 积分值 最多保留两位小数 (recharge 正数 consume 负数)
// clientTradeSn       //必填 客户端交易编号 不超过32位字符串
// originClientTradeSn //选填 原客户端交易编号 冲正时必填
// mallId              //条件可选，视现场需求而定
func (ZhengHongPoints) PointsConsume(ctx context.Context, db *gorm.DB, salesID, openid string,
	clientTradeSn string, tradeAmount float64, mallId string) (err error) {
	var WechatUserInfo models.MaWechatUser
	var WechatUserCount int64
	db.Model(&models.MaWechatUser{}).
		Where("open_id = ?", openid).
		Take(&WechatUserInfo).
		Count(&WechatUserCount)
	if WechatUserCount == 0 || WechatUserInfo.Phone == "" {
		err = errorx.New("【正弘城】当前用户未注册", 100099)
		return
	}
	// 验证正弘系统会否注册用户
	memberRsp, err := ZhengHongPoints{}.GetMemberInfo(ctx, db, salesID, WechatUserInfo.Phone, WechatUserInfo.OpenID)
	if memberRsp.ID == "" || err != nil {
		err = errorx.New("【正弘城】当前用户未注册", 100099)
		return
	}
	if tradeAmount >= 0 {
		return errorx.New("交易数额错误", -1)
	}
	if clientTradeSn == "" {
		return errorx.New("客户端交易编号不能为空", -1)
	}

	var PostData = make(map[string]interface{})
	PostData["cardNo"] = memberRsp.CardNo
	PostData["tradeType"] = "consume" // recharge 增加 consume 扣减 revoke 冲正
	PostData["remark"] = "大道智创商品消费"
	PostData["tradeAmount"] = strconv.FormatFloat(tradeAmount, 'f', -1, 64)
	PostData["clientTradeSn"] = clientTradeSn
	if mallId != "" {
		PostData["mallId"] = mallId
	}

	bytes, _ := json.Marshal(&PostData)
	var params = string(bytes)
	queryString, err1 := ZhengHongPoints{}.GetQueryString(ctx, salesID, map[string]string{}, &params)
	if err1 != nil {
		return err1
	}

	QueryURL := config.Config.ZhenghongPoints.BaseURL + "/api/v3/card/credit/trade?" + queryString
	statusCode, bytes, err := helper.Net{}.Request(ctx, "POST", QueryURL, map[string]string{}, PostData)
	var rsp ZhenghongCommonReq
	json.Unmarshal(bytes, &rsp)
	logx.Info(ctx, "balance trade", logx.Any("queryURL", QueryURL), logx.Any("PostData", PostData), logx.Any("statusCode", statusCode), logx.Any("bytes", string(bytes)), logx.Any("err", err))
	if rsp.ErrorCode != ZHENGHONG_SUCCESS {
		err = errorx.New(rsp.ErrorMessage)
		return
	}
	return nil
}

// 积分冲正
func (ZhengHongPoints) PointsReverse(ctx context.Context, db *gorm.DB, salesID, openid string,
	refundOrderID, orderID string, tradeAmount float64, mallId string) (err error) {
	var WechatUserInfo models.MaWechatUser
	var WechatUserCount int64
	mysql.NewDB().Model(&models.MaWechatUser{}).
		Where("open_id = ?", openid).
		Take(&WechatUserInfo).
		Count(&WechatUserCount)
	if WechatUserCount == 0 || WechatUserInfo.Phone == "" {
		err = errorx.New("【正弘城】当前用户未注册", 100099)
		return
	}
	// 验证正弘系统会否注册用户
	memberRsp, err := ZhengHongPoints{}.GetMemberInfo(ctx, db, salesID, WechatUserInfo.Phone, WechatUserInfo.OpenID)
	if memberRsp.ID == "" || err != nil {
		err = errorx.New("【正弘城】当前用户未注册", 100099)
		return
	}

	var PostData = make(map[string]interface{})
	PostData["cardNo"] = memberRsp.CardNo
	PostData["tradeType"] = "revoke"
	PostData["remark"] = "大道智创商品消费退款"
	PostData["tradeAmount"] = strconv.FormatFloat(tradeAmount, 'f', -1, 64)
	PostData["clientTradeSn"] = refundOrderID
	PostData["originClientTradeSn"] = orderID
	if mallId != "" {
		PostData["mallId"] = mallId
	}

	bytes, _ := json.Marshal(&PostData)
	var params = string(bytes)
	queryString, err1 := ZhengHongPoints{}.GetQueryString(ctx, salesID, map[string]string{}, &params)
	if err1 != nil {
		return err1
	}

	QueryURL := config.Config.ZhenghongPoints.BaseURL + "/api/v3/card/credit/trade?" + queryString
	statusCode, bytes, err := helper.Net{}.Request(ctx, "POST", QueryURL, map[string]string{}, PostData)
	var rsp ZhenghongCommonReq
	json.Unmarshal(bytes, &rsp)
	logx.Info(ctx, "balance reverse", logx.Any("queryURL", QueryURL), logx.Any("PostData", PostData), logx.Any("statusCode", statusCode), logx.Any("bytes", string(bytes)), logx.Any("err", err))
	if rsp.ErrorCode != ZHENGHONG_SUCCESS {
		err = errorx.New(rsp.ErrorMessage)
		return
	}
	return
}
